package algorithm.sphericharmonics;

import algorithm.fft.Complex;


public class ScaledAssociatedLegenedrePolynomialFunct extends MathFunct {
	//private static final float PI=(float)Math.PI;
	public static void main(String[] args){
		System.out.println(k(0)); 
	}
	public static int k(int m){
	   if (m==0){
		   return 1; 
	   }else {
		   return m*k(m-1); 
	   }
	}
	public static ComplexSphere yfunction(int l,int m, float theta, float phi){
		float v=pfunct(l,m,(float)Math.cos(theta)); 
		if (v<0){
			return new ComplexSphere(-v,phi*m+PI); 
		}else {
			return new ComplexSphere(v, phi*m);
		}
	}
	public static float pfunct(int l,int m, float x){
		float a=k(l-m);
		float b=k(l+m); 
		float f=(float)Math.sqrt(a/b)*(sqrt((2*l+1.0f)/PI)/2); 
		//System.out.println("k:"+(b/a)+"="+b+"/"+(a)); 
		switch (l){
		case 0:
			return p0(m,x)*(sqrt((2*l+1)/PI)/2); 
		case 1:
			return p1(m,x)*f; 
		case 2:
			return p2(m,x)*f; 
		case 3:
			return p3(m,x)*f; 
		case 4:
			return p4(m,x)*f; 
		}
		throw new RuntimeException("not implemented");  
	}
	private static float p0(int m,float x){
		if (m==0){
			return 1; 
		}
		throw new RuntimeException("out of boundary "+m);
	}

	private static float p1(int m,float x){
		switch(m){
		case -1:
			return -sqrt((1-x*x))/(-2); 
		case 0:
			return x; 
		case 1: 
			return -sqrt((1-x*x));  
		}
		throw new RuntimeException("out of boundary");
	}
	private static float p2(int m,float x){
		switch(m){
		case -2:return 3*(1-x*x)/24; 
		case -1: return -3*x*sqrt(1-x*x)/(-6);
		case  0:
			return (3*x*x-1)/2; 
		case  1:
			return -3*x*sqrt(1-x*x); 
		case  2:
			return 3*(1-x*x); 
		}
		throw new RuntimeException("out of boundary");
	}	
	private static float p3(int m, float x){ 
		switch(m){
		case -3:
			return -15*pow((1-x*x),1.5f)/(-720);
		case -2:
			return 15*x*(1-x*x)/120; 
		case -1:
			return -(5*x*x-1)*sqrt(1-x*x)*3/2*(-1.0f/12);
		case  0:
			return (5*x*x*x-3*x)/2; 
		case 1:
			return -(5*x*x-1)*sqrt(1-x*x)*3/2.0f;  
		case 2:
			return 15*x*(1-x*x); 
		case 3:
			return -15*pow((1-x*x),1.5f); 
		}
		throw new RuntimeException("out of boundary");
	}
	private static float p4(int m,float x){
		switch(m){
		case -4:
			return 105*(1-x*x)*(1-x*x)/40320; 
		case -3:
			return -105*x*pow((1-x*x),1.5f)/(-5040); 
		case -2:
			return (15.0f/2)*(7*x*x-1)*(1-x*x)/360;
		case -1:
			return (7*x*x*x-3*x)*sqrt(1-x*x)*(-5.0f/2)/(-20);
		case 0:
			return (35*x*x*x*x-30*x*x+3)/8; 
		case 1:
			return (7*x*x*x-3*x)*sqrt(1-x*x)*(-5.0f/2); 
		case 2:
			return (15/2.0f)*(7*x*x-1)*(1-x*x); 
		case 3:
			return -105*x*pow((1-x*x),1.5f); 
		case 4:
			return 105*(1-x*x)*(1-x*x); 
		}
		throw new RuntimeException("out of boundary");
	}
}
